package exadel.calc;

import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * BasicCalculator
 *
 */
public class BasicCalculator implements Calculator
{
	Scanner con;
	private int cash;
	Coins money;
	private SortedMap<Integer, Integer> unit = null;
	
	public BasicCalculator(int cash,int count){
		if(setCash(cash)) {
			money = new Coins(count);
			setUnit();
		}
	}
	
	public int getCash() {
		return cash;
	}
	
	private boolean setCash(int cash) {
		if(cash <= 0) return false;
		this.cash = cash;			
		return true;
	}
	
	private void setUnit(){
		unit = new TreeMap<Integer, Integer>();
		unit.putAll(money.rating);
		//getUnit();
	}
	
	private void getUnit() throws NullPointerException {
		System.out.println("issued coins:");
		Iterator<Entry<Integer, Integer>> it = unit.entrySet().iterator();
	    while( it.hasNext() )
	    {
	        Entry<Integer, Integer> me = it.next();
	        System.out.println(me.getKey() + "  " + me.getValue() + "\n");
	    }
	}
	
	private Integer getUnitKey(){

		Iterator<Entry<Integer, Integer>> it = unit.entrySet().iterator();
	    while( it.hasNext() )
	    {
	        Entry<Integer, Integer> me = it.next();
	        if(me.getValue() != 0){ 
	        	unit.put(me.getKey(), unit.get(me.getKey()) - 1);
	        	return me.getKey();
	        }
	    }
	    return null;
	}

	public Map<Integer, Integer> calculator() throws IllegalArgumentException,
			IllegalStateException, NullPointerException, NoSuchElementException, CalculatorFailedException {
		if (cash > 0) {
			for (int resoult = money.searchCoins(); cash > 0;) {
				if (cash - resoult >= 0	&& cash - resoult >= money.rating.firstKey()) {
					cash -= resoult;
					unit.put(resoult, unit.get(resoult) + 1);
				} else if (cash - resoult * money.rating.get(resoult) == 0) {
					cash -= resoult * money.rating.get(resoult);
					unit.put(resoult, unit.get(resoult) + 1);

				} else {
					resoult = getUnitKey();
					cash += resoult;
					money.rating.remove(resoult);
				}
				resoult = money.searchCoins();
			}
		}
		else new CalculatorFailedException();
		
		return unit;
	}
		//INNER CLASS
		private class Coins {
			
			private SortedMap<Integer, Integer> rating = null;
		
			public Coins(int count){
				if(count <= 0) count = 5;
				setRating(count);
			}
			
			private void setRating(int count) {
				rating = new TreeMap<Integer, Integer>();
				con = new Scanner(System.in);
		        for(int i = 0, key = 0; i < count; ){
		        	System.out.println("value of coins:");
		    			key = con.nextInt();
		    			if(key >= 1) {
		    				rating.put(key,0);
		    				i++;
		    			}
		        }
			}
			
			private void getRating() {
				System.out.println("coins:");
				Iterator<Entry<Integer, Integer>> it = rating.entrySet().iterator();
				while (it.hasNext()) {
					Entry<Integer, Integer> me = it.next();
					System.out.println(me.getKey() + "  " + me.getValue() + "\n");
				}
			}
	
			//Сalculation of weights for coins
			private void weighCoins() {
				Iterator<Entry<Integer, Integer>> it = rating.entrySet().iterator();
				Entry<Integer, Integer> me;
				while (it.hasNext()) {
					me = it.next();
					if(me.getKey() > 0)
						me.setValue(cash / me.getKey()) ;
				}	
			}
			
		//Find coins with the smallest weight
		private Integer searchCoins() {		
			Integer key = 0;
			Iterator<Entry<Integer, Integer>> it = rating.entrySet().iterator();
			Entry<Integer, Integer> me;
			weighCoins();
			
			while(it.hasNext()) {
				me = it.next();
				if(me.getValue() > 0 && me.getKey() > 0 && key < me.getKey()) {
					if(key <= cash){
						key = me.getKey();
					}
				}
			}
			return key;
		}
	}
}
